package com.xiguanlezz.cn.codec;

import com.xiguanlezz.cn.StringPaddingUtils;
import com.xiguanlezz.cn.protocol.RpcHeader;
import com.xiguanlezz.cn.protocol.RpcProtocol;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @Author：习惯了种种
 * @CreateDate：2024/11/4 13:02
 * @Description：Rpc消息编码器
 */
public class RpcEncoder extends MessageToByteEncoder<RpcProtocol<Object>>
        // 为什么要实现这个鬼接口，接口只是提供了某个序列化器。因为Java只支持单继承
        implements RpcCodec {

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, RpcProtocol<Object> rpcProtocol, ByteBuf out) throws Exception {
        if (Objects.isNull(rpcProtocol)) {
            return;
        }

        RpcHeader rpcHeader = rpcProtocol.getHeader();
        // 1. 写入请求头
        out.writeShort(rpcHeader.getMagicNumber());
        out.writeByte(rpcHeader.getMessageType());
        out.writeByte(rpcHeader.getMessageStatus());
        out.writeLong(rpcHeader.getMessageId());
        // 注意：serializerType写入时，如果不足16位需要前面补#
        out.writeCharSequence(
                StringPaddingUtils.paddingString(rpcHeader.getSerializerType(), StringPaddingUtils.STRING_MAX_LENGTH),
                StandardCharsets.UTF_8);

        // 2. 写入请求体
        Object body = rpcProtocol.getBody();
        byte[] bs = getJdkSerializer().serialize(body);
        // 为什么在即将写入请求体时，才将dataLength写入ByteBuf？
        // 为了业务层面不直接感知dataLength，换句话说就是发数据的时候不需要计算dataLength并赋值给RpcHeader
        out.writeInt(bs.length);
        out.writeBytes(bs);
    }
}
